<?php

/**
 * contact : 刘经理 19326416371
 * company : 版权所属 四川北星惯牌科技有限公司
 **/

namespace app\common\manager\prepay\gateway;

use addons\epay\library\Service;
use app\common\manager\BaseManager;
use app\common\manager\OrderManager;
use app\common\manager\PayLogManager;
use app\common\manager\UserAccountManager;
use app\common\model\Address;
use app\common\model\assistant\Assistant as AssistantModel;
use app\common\model\AssistantOrder;
use app\common\model\Config;
use app\common\model\Coupon;
use app\common\model\Order;
use app\common\model\UserAccount;
use app\common\model\UserCoupon;
use think\Db;
use think\Exception;

class Assistant
{
    CONST METHOD = 'Assistant';

    CONST TYPE_ALIPAY = 1;
    CONST TYPE_WECHAT = 2;
    public function order($user, $request,$isTrans=true)
    {
        $is_success = 0;
        if ($isTrans)
            Db::startTrans();
        try {
            $prePayment = null;
            $type = $request['type'] ?? 'wechat';
            $orderId = $request['orderId'] ?? '';
            $method = $request['method'] ?? 'JSAPI';
            //$relationId = $request['relationId'] ?? 0;
            $is_balance = $request['isBalance'] ?? 0;
            $userCouponId = $request['userCouponId'] ?? 0;
            $assistantIds = $request['assistantIds'] ?? '';
            $startTime = $request['startTime'] ?? '';
            $endTime = $request['endTime'] ?? '';
            $addressId = $request['addressId'] ?? '';
            if (!$user->is_authentication){
                throw new Exception('您未实名认证，无法操作');
            }

            if (!$addressId){
                throw new Exception('请选择地址');
            }

            if (!$startTime || !$endTime){
                throw new Exception('请选择正确的时间段');
            }
            $startTimeStep = strtotime($startTime);
            $endTimeStep = strtotime($endTime);
            if ($startTimeStep > $endTimeStep){
                throw new Exception('开始时间不能大于结束时间');
            }

            if(!$assistantIds){
                throw new Exception('请选择助教');
            }
            $addressInfo = Address::where('id',$addressId)->where('user_id',$user->id)->where('delete',Address::DELETE_NO)->find();
            if (!$addressInfo){
                throw new Exception('地址信息有误');
            }
            $lat = $addressInfo['lat'];
            $lng = $addressInfo['lng'];
            $address = $addressInfo['address'];
            $orderInfo = Order::where('po_id',$orderId)->where('type',Order::TYPE_ASSISTANT)->where('expire_time','>',time())->find();
            if ($orderInfo){
                $assistantIds = $orderInfo['assistantIds'];
            }
            $h = intval(date('H',time()));
            $i = date('i',time());
            $compare = $h.$i;
            $assistantModel = new AssistantModel();
            $assistantInfo = $assistantModel->alias('a')
                ->join('assistant_time t','t.assistant_id = a.id','inner')
                ->where('a.id',$assistantIds)
                ->where('a.user_id','<>',$user->id)
                ->where('t.compare_start','<=',$compare)
                ->where('t.compare_end','>=',$compare)
                ->where('a.status',AssistantModel::STATUS_ENABLE)
                ->where('a.review_status',AssistantModel::REVIEW_STATUS_PASS)
                ->where('a.order_switch',AssistantModel::ORDER_SWITCH_ON)
                ->where('a.in_service',AssistantModel::IN_SERVICE_STATUS_OFF)
                ->field('a.id,a.user_id,a.nickname,a.avatar,a.gender,a.birthday,a.order_switch,a.in_service,a.level,a.introduce,a.type,a.store_id,a.assistant_price,a.time_unit,a.lng,a.lat,a.address')
                ->group('a.id')
                ->find();

            $totalTime = bcsub($endTimeStep,$startTimeStep,0);
            $totalMinute = bcdiv($totalTime,60,2);

            if ($assistantInfo->user_id == $user->id) {
                throw new Exception('助教不能是自己');
            }
            $totalNumber = ceil(bcdiv($totalMinute,$assistantInfo['time_unit'],2));
            $assistantMoney = bcmul($totalNumber,$assistantInfo['assistant_price'],2);

            $assistantTravelAmount = $exceedAmount = 0.00;
            $baseMileage = Config::where('name','basic_mileage')->value('value');
            $baseMileagePrice = Config::where('name','basic_mileage_price')->value('value');
            $exceed_price = Config::where('name','exceed_price')->value('value');

            $distance = haversine($lat,$lng,$assistantInfo['lat'],$assistantInfo['lng']);
            $exceed_distance = ceil(bcsub($distance,$baseMileage,2));
            if($exceed_distance){
                $exceedAmount = bcmul($exceed_distance,$exceed_price,2);
            }
            $exceedAmount = max($exceedAmount, 0.00);
            $assistantTravelAmount = bcadd($baseMileagePrice,$exceedAmount,2);

            $info = \app\common\model\assistant\Order::where('assistant_id',$assistantInfo['id'])
                ->where('status','<>',\app\common\model\assistant\Order::STATUS_END)
                ->where('pay_status',\app\common\model\assistant\Order::PAY_STATUS_YES)
                ->select();
            if ($info){
                foreach ($info as $order) {
                    if ($order['status'] == \app\common\model\assistant\Order::STATUS_REFUND && $order['pay_status'] == \app\common\model\assistant\Order::PAY_STATUS_REFUND){
                        continue;
                    }
                    if ($order['order_start_time'] <= $startTimeStep && $order['order_end_time'] >= $startTimeStep){
                        throw new Exception($assistantInfo['nickname'].'助教已有订单，无法参与');
                    }else if($order['order_start_time'] <= $endTimeStep && $order['order_end_time'] >= $endTimeStep){
                        throw new Exception($assistantInfo['nickname'].'助教已有订单，无法参与');
                    }
                }
            }

            $userCouponInfo = null;
            if (!$orderInfo) {
                if ($userCouponId) {
                    $userCouponInfo = UserCoupon::where('id', $userCouponId)->where('user_id', $user->id)->find();
                    if (!$userCouponInfo) {
                        throw new Exception('优惠券信息有误，无法使用');
                    }

                    if ($userCouponInfo['expires_time'] < time()) {
                        throw new Exception('优惠券已过期，无法使用');
                    }

                    if ($userCouponInfo['detail'] != Coupon::DETAIL_PLAYER) {
                        throw new Exception('优惠券类型有误，无法使用');
                    }

                    if ($userCouponInfo['block'] == UserCoupon::BLOCK_YES) {
                        throw new Exception('优惠券已被使用，无法使用');
                    }

                }
            }else{
                $userCouponId = $orderInfo['user_coupon_id'] ?? 0;
                $userCouponInfo = UserCoupon::where('id', $userCouponId)->where('user_id', $user->id)->find();
            }

            $time_expire = config('app.time_expire') ?? 5;
            $time_expire = bcadd(time(), bcmul($time_expire,60));
            if ($type == 'wechat'){
                $time_expire = date('YmdHis', $time_expire);
            }else if ($type == 'alipay'){
                $time_expire = date('Y-m-d H:i:s', $time_expire);
            }

            /**
             * 如果传参orderId ,在上面条件通过的情况下，将拉起传参过来的订单
             */
            $result = [];
            $pref_amount = 0.00;
            if ( !empty($orderInfo) ) {
                $real_money = bcadd($orderInfo['real_money'],0,2);
                $order = $orderInfo['order'];
                $orderData = ['id'=>$orderId,'time_expire'=>$orderInfo['expire_time']];
                $result['code'] = BaseManager::$successCode;
                $result['message'] = BaseManager::$successMessage;
                $result['data'] = $orderData;
                $prePayment = json_decode($orderInfo['pre_payment'],true);
            }else{
                $money = $real_money = bcadd($assistantMoney,$assistantTravelAmount,2);
                if($userCouponInfo){

                    if ($userCouponInfo['limit_amount'] > $assistantMoney) {
                        throw new Exception('当前金额未满足优惠券使用条件，无法使用');
                    }

                    if ($userCouponInfo['type'] == Coupon::TYPE_FULL) {
                        $real_money = bcsub($money,$userCouponInfo['amount'], 2);
                        $pref_amount = $userCouponInfo['amount'];
                    } else if ($userCouponInfo['type'] == Coupon::TYPE_DISCOUNT && $userCouponInfo['rate'] > 0) {
                        $real_money = bcsub($money,bcdiv(bcmul($assistantMoney, $userCouponInfo['rate'], 2), 100, 2),2);
                        $pref_amount = bcsub($money, $real_money, 2);
                    }

                    if (!UserCoupon::where('id', $userCouponInfo['id'])->update(['block' => UserCoupon::BLOCK_YES, 'update_time' => time()])) {
                        throw new Exception('优惠券使用失败，请稍后再试');
                    }
                }

                $order = orderNum();
                $data['order'] = $order;
                $data['user_id'] = $user->id;
                $data['order_money'] = $money;
                $data['real_money'] = $real_money;
                $data['user_coupon_id'] = $userCouponInfo['id']??0;
                $data['pref_money'] = $pref_amount;
                $data['relation_id'] = 0;
                $data['assistant_ids'] = $assistantIds;
                $data['is_balance'] = $is_balance;
                $data['expire_time'] = strtotime($time_expire);
                $data['extend_param'] = serialize([
                    'basic_mileage'=>$baseMileage,
                    'basic_mileage_price'=>$baseMileagePrice,
                    'exceed_price'=>$exceed_price,
                    'address'=>$address,
                    'lng'=>$lng,
                    'lat'=>$lat,
                    'distance'=>$distance,
                    'exceed_distance'=>$exceed_distance,
                    'distance_amount'=>$assistantTravelAmount,
                    'exceed_amount'=>$exceedAmount
                ]);
                $data['ct_date'] = time();
                $result = OrderManager::Order($user,$data,\app\common\model\Order::TYPE_ASSISTANT,false);
                if ($result['code'] != OrderManager::$successCode){
                    throw new Exception($result['message']);
                }
                $result['data']['time_expire'] = strtotime($time_expire);

                $assistantOrder = [
                    'assistant_id' => $assistantInfo['id'],
                    'user_id' => $assistantInfo['user_id'],
                    'order' => $order,
                    'orderer' => $user->id,
                    'order_id' => $result['data']['id'],
                    'amount' => $assistantMoney,
                    'discount_amount' => $pref_amount,
                    'real_amount' => $real_money,
                    'distance_amount' => $assistantTravelAmount,
                    'order_start_time' => $startTimeStep,
                    'order_end_time' => $endTimeStep,
                    'extends'=>serialize([
                        'basic_mileage'=>$baseMileage,
                        'basic_mileage_price'=>$baseMileagePrice,
                        'exceed_price'=>$exceed_price,
                        'address'=>$address,
                        'lng'=>$lng,
                        'lat'=>$lat,
                        'distance'=>$distance,
                        'exceed_distance'=>$exceed_distance,
                        'distance_amount'=>$assistantTravelAmount,
                        'exceed_amount'=>$exceedAmount
                    ]),
                    'create_time' => time(),
                    'update_time' => time(),
                ];

                if(!\app\common\model\assistant\Order::create($assistantOrder)){
                    throw new Exception('助教订单创建失败');
                }

                $userAssistantOrder = [
                    'assistant_id' => $assistantInfo['id'],
                    'user_id' => $user->id,
                    'order' => $order,
                    'order_id' => $result['data']['id'],
                    'amount' => $assistantMoney,
                    'discount_amount' => $pref_amount,
                    'real_amount' => $real_money,
                    'distance_amount' => $assistantTravelAmount,
                    'order_start_time' => $startTimeStep,
                    'order_end_time' => $endTimeStep,
                    'extends'=>serialize([
                        'basic_mileage'=>$baseMileage,
                        'basic_mileage_price'=>$baseMileagePrice,
                        'exceed_price'=>$exceed_price,
                        'address'=>$address,
                        'lng'=>$lng,
                        'lat'=>$lat,
                        'distance'=>$distance,
                        'exceed_distance'=>$exceed_distance,
                        'distance_amount'=>$assistantTravelAmount,
                        'exceed_amount'=>$exceedAmount
                    ]),
                    'create_time' => time(),
                    'update_time' => time(),
                ];

                if(!AssistantOrder::create($userAssistantOrder)){
                    throw new Exception('用户助教订单创建失败');
                }
            }



            if ($is_balance && $result['code']==OrderManager::$successCode){
                $userAccount = UserAccount::where('user_id',$user->id)->find();
                if (!$userAccount){
                    throw new Exception('当前用户账户信息有误，无法使用此功能');
                }

                if ($userCouponInfo){
                    if (!UserCoupon::where('id', $userCouponInfo['id'])->update(['block' => UserCoupon::BLOCK_NO, 'status' => UserCoupon::STATUS_USED, 'update_time' => time()])) {
                        throw new Exception('优惠券使用失败，请稍后再试');
                    }
                }

                $result2 = UserAccountManager::money($user->id,$real_money,UserAccountManager::CHANGE_TYPE_PAYMENT,time(),UserAccountManager::TYPE_TEAM,['relation_id'=>$result['data']['id']],false);
                if ($result2['code']!=UserAccountManager::$successCode){
                    throw new Exception($result2['message']);
                }
                $resUpdate = ['pay_state'=>Order::PAY_STATE_SUCCESS,'pay_date'=>time(),'up_date'=>time()];
                $resultOrder = OrderManager::modify($result['data']['id'],$resUpdate,false);
                if ($resultOrder['code']!=OrderManager::$successCode){
                    throw new Exception($resultOrder['message']);
                }

                $upgradeResult = UserAccountManager::LevelUpgrade($user->id,'upgrade',false);
                if ($upgradeResult['code']!=UserAccountManager::$successCode){
                    throw new Exception($upgradeResult['message']);
                }

                if (!UserAccount::where(['user_id'=>$user->id])->update([
                    'assistant_count'=>Db::raw('assistant_count + 1'),
                    'version'=>Db::raw('version + 1'),
                    'updatetime'=>time()
                ])) {
                    throw new Exception('用户账户信息更新失败');
                }

                if(!\app\common\model\assistant\Order::where('order_id',$result['data']['id'])->update(['pay_status'=>\app\common\model\assistant\Order::PAY_STATUS_YES,'update_time'=>time()])){
                    throw new Exception('助教订单状态修改失败');
                }

                if(!AssistantOrder::where('order_id',$result['data']['id'])->update(['pay_status'=>AssistantOrder::PAY_STATUS_YES,'update_time'=>time()])){
                    throw new Exception('用户助教订单状态修改失败');
                }

                $is_success = 1;
                if ($isTrans)
                    Db::commit();
                $prePayment = null;

            }else{
                if (!$prePayment){
                    $result1 = PayLogManager::record(['user_id'=>$user->id,'method'=>self::METHOD,'type'=> $type=='alipay' ? self::TYPE_ALIPAY : self::TYPE_WECHAT,'order'=>$order,'money'=>$real_money,'create_time'=>time()]);
                    $returnUrl = \config('app.returnUrl');
                    if ($type=='wechat'){
                        $notifyUrl = \config('app.notifyWechatUrl');
                    }else if ($type=='alipay'){
                        $notifyUrl = \config('app.notifyAlipayUrl');
                    }
                    if ($result['code'] == OrderManager::$successCode && $result1['code'] == PayLogManager::$successCode) {
                        if ($isTrans)
                            Db::commit();

                        //file_put_contents('a.txt',$notifyUrl,FILE_APPEND);
                        $prePayment = Service::submitOrder($real_money,$order,$type,\app\common\model\Order::TYPE_ARRAY[\app\common\model\Order::TYPE_ASSISTANT]['name'],$notifyUrl,$returnUrl,$method,$user->open_id,$time_expire,['relation_id'=>$orderId]);
                        $resUpdate = ['pre_payment'=>$prePayment,'up_date'=>time()];
                        $resultOrder = OrderManager::modify($result['data']['id'],$resUpdate,false);
                        if ($resultOrder['code']!=OrderManager::$successCode){
                            throw new Exception('订单信息修改失败');
                        }
                        if($result1['data']['id']){
                            $id = $result1['data']['id'];
                            $update = ['request'=>serialize($prePayment)];
                            PayLogManager::modify($id,$update);
                        }
                    }else{
                        throw new Exception($result['message'].'或'.$result1['message']);
                    }
                }

            }

            return ['code'=>1,'message'=>'success','data'=>['order'=>$result['data'],'is_success'=>$is_success??0,'pre_payment'=>$prePayment]];
        }catch (Exception $exception){
            if ($isTrans)
                Db::rollback();
            return ['code'=>0,'message'=>$exception->getMessage().$exception->getLine(),'data'=>null];
        }
    }
}